﻿package zf.data.ds
{

	/**
	 * 不重复的链表数据池。在设定的数据池中，获取不重复的数据。获取一个数据，数据池将减少一个。
	 * 请注意，他将比不重复的数组数据池慢
	 * @author mike.zhang
	 * @langversion 3.0 
	 * @playerversion Flash 9 
	 * 
	 */
	public class NotechoLinkedList
	{
		private var rsll:RingSLinkedList;
		private var _data:RingSLinkedList;
		private var _cyc:Boolean=false;
		/**
		 * 创建一个不重复数据池 
		 * @param args 要往数据池中添加的数据
		 * 
		 */
		public function NotechoLinkedList (... args)
		{
			rsll=new RingSLinkedList  ;
			var l:uint=args.length;
			if (args.length > 0)
			{
				append.apply (this,args);
			}
		}
		/**
		 * 是否循环取数据，默认为flase，不循环。如果要设置为true，请使用 backupData() 来备份数据。如果设置为true，在数据池中数据被取完后，将用备份的数据重新填充数据池，使其可以继续取出数据。如果设置为false,数据池中的数据全部取完后将为null
		 * @return Boolean
		 * @see #backupData
		 * 
		 */

		public function get cyc ():Boolean
		{
			return _cyc;
		}

		public function set cyc (v:Boolean):void
		{
			_cyc=v;
		}
		/**
		 * 备份当前数据池中数据。执行此函数后，如果 cyc 为 true 时，数据池中的数据取完后将填充备份的数据。
		 * 
		 */
		public function backupData ():void
		{
			_data=rsll.cloneR();
		}
		/**
		 * 数据池中数据，其类型是环单向链表，你也可以通过 append() 方法来给数据池中添加数据。 
		 * @return 环单向链表
		 * @see #append()
		 * @see #RingSLinkedList
		 */
		public function get data ():RingSLinkedList
		{
			return _data;
		}

		public function set data (v:RingSLinkedList):void
		{
			_data=v;
		}
		/**
		 * 向数据池中添加数据 
		 * @param args 要往数据池中添加的数据
		 * 
		 */
		public function append (... args):void
		{
			var l:uint=args.length;
			for (var i:uint=0; i < l; i++)
			{
				rsll.append (args[i]);
			}
		}
		/**
		 * 随机取出一个数据。如果数据池中有数据，则随机取出一个数据并返回，如果数据池已经为空，且 cyc 为false,则返回 null， 若 cyc 为true，那么数据池将被重新填充
		 * @return 数据或null
		 * 
		 */
		public function popRandomData ():*
		{
			//var p:SListPointer=rsll.creatPointer();
			var index:uint=Math.floor(Math.random() * rsll.length * 10) % rsll.length;
			/*var i:uint=0;
			while(i<index)
			{
			p.next();
			i++;
			}
			rsll.splice(p,1);
			return p.node.data;*/
			return popIndexData(index);
		}
		/**
		 * 取出数据池中下标为 index 的数据 
		 * @param index 要获取数据的下标
		 * @return 数据或null
		 * 
		 */
		public function popIndexData (index:uint=0):*
		{
			if (rsll.isEmpty())
			{
				if (_cyc)
				{
					rsll=_data.cloneR();
				}
				else
				{
					return null;
				}
			}
			var p:SListPointer=rsll.creatPointer();
			if (index >= rsll.length)
			{
				index%= rsll.length;
			}
			//var index:uint=Math.floor(Math.random()*rsll.length*10)%rsll.length;
			var i:uint=0;
			while (i < index)
			{
				p.next ();
				i++;
			}
			//trace(p);
			rsll.splice (p,1);
			//trace(rsll);
			return p.node.data;
		}
		/**
		 * 获取数据池中当前数据的个数 
		 * @return 数据个数
		 * 
		 */
		public function get length ():uint
		{
			return rsll.length;
		}
	}
}